﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Farigola.Engine
{
    /// <summary>
    /// One error, occurs in the appliaction.
    /// </summary>
    public class AppError
    {
        public DateTime When;

        public string Code;

        /// <summary>
        /// Parameter 1 of the error.
        /// </summary>
        public string Param;

        /// <summary>
        /// Parameter 1 of the error.
        /// </summary>
        public string Param2;

        /// <summary>
        /// The exception occurs.
        /// </summary>
        public Exception Exception;

        public AppError(string code)
        {
            When = DateTime.Now;
            Code = code;
        }

        // params: by position

        // params, code/Value
    }

    /// <summary>
    /// an application task activity.
    /// </summary>
    public class AppTask
    {
        DateTime When;

        public string Code;

        /// <summary>
        /// End status of the task: Ok, Error,...
        /// </summary>
        public AppActivityStatus Status;
 
        // list of errors occurs on the task 
        List<AppError> _listError;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="code"></param>
        public AppTask(string code)
        {
            When = DateTime.Now;
            Code = code;
        }

        public void AddError(string errCode)
        {
            if (_listError == null)
                _listError = new List<AppError>();

            AppError err = new AppError(errCode);
            _listError.Add(err);
        }

        public void AddError(string errCode, string param, string param2)
        {
            if (_listError == null)
                _listError = new List<AppError>();

            AppError err = new AppError(errCode);
            err.Param = param;
            err.Param2 = param2;
            _listError.Add(err);
        }

        public void Stop(AppActivityStatus status)
        {
            Status = status;
        }

        public AppError GetLastError()
        {
            if (_listError == null)
                return null;

            return _listError[_listError.Count - 1];
        }

    }

    //*************************************************************************
    public enum AppActivityStatus
    {
        // the first item is the default set
        InProgress,
        EndOk,
        EndError,
        AbortError
    }

    //*************************************************************************
    /// <summary>
    /// To manage the activity of the application.
    /// manage actions, errors, ...
    /// </summary>
    public class AppActivityMgr
    {
        /// <summary>
        /// Manager of errors/exceptions occurs in the engine.
        /// save errors of the last action (last called method).
        /// </summary>
        private ErrorMgr _errorMgr;

        /// <summary>
        /// List of tasks.
        /// </summary>
        private List<AppTask> _listAppTask = new List<AppTask>();

        /// <summary>
        /// The current application task
        /// </summary>
        private AppTask _currAppTask;

        //---------------------------------------------------------------------
        /// <summary>
        /// return the previous current task.
        /// </summary>
        /// <returns></returns>
        public AppTask GetPreviousTask()
        {
            if (_listAppTask.Count == 0)
                // no previous task
                return null;

            return _listAppTask[_listAppTask.Count - 1];
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// get the last error occurs in the engine.
        /// </summary>
        /// <returns></returns>
        public AppError GetLastError()
        {
            // get the current task
            if (_currAppTask != null)
            {
                return _currAppTask.GetLastError();
            }

            // get the previous task
            AppTask prevTask = GetPreviousTask();
            if (prevTask == null)
                return null;

            return prevTask.GetLastError();
        }

        //=====================================================================
        #region Task methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Put the current task to the previous task if already present.
        /// now there are no current task.
        /// </summary>
        /// <returns></returns>
        private bool PutCurrentTaskToPrevious()
        {
            if (_currAppTask == null)
                return false;

            // archive the current task
            _listAppTask.Add(_currAppTask);

            // now no current task present
            _currAppTask = null;
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        ///  start a new task, 
        ///  create a taks, becomes the current one.
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public bool StartTask(string taskCode)
        {
            if (taskCode == null)
                return false;

            taskCode = taskCode.Trim();
            if (taskCode.Length == 0)
                return false;

            // save the previous task if already present
            PutCurrentTaskToPrevious();

            // create a taks, becomes the current one
            _currAppTask = new AppTask(taskCode);

            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Stop the current tak on error status.
        /// </summary>
        /// <param name="?"></param>
        /// <returns></returns>
        public bool StopCurrentTask(AppActivityStatus status)
        {
            if(_currAppTask==null)
                return false;

            _currAppTask.Stop(status);

            // save the previous task if already present
            PutCurrentTaskToPrevious();

            return true;
        }

        //---------------------------------------------------------------------
        // task ends ok
        public bool StopTaskOk()
        {
            StopCurrentTask(AppActivityStatus.EndOk);
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Add an error on the current task.
        /// Create one if no task present.
        /// 
        /// Stop the current task.
        /// </summary>
        /// <param name="errCode"></param>
        /// <returns></returns>
        public bool AddErrorRetFalse(string errCode, string param, string param2)
        {
            if (_currAppTask == null)
                StartTask("Undefined");

            _currAppTask.AddError(errCode, param, param2);

            // stop the current tak on error status
            StopCurrentTask(AppActivityStatus.EndError);
            return false;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Add an error on the current task.
        /// Create one if no task present.
        /// 
        /// Stop the current task.
        /// </summary>
        /// <param name="errCode"></param>
        /// <returns></returns>
        public bool AddErrorRetFalse(string errCode, string param)
        {
            return AddErrorRetFalse(errCode, param, "");
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Add an error on the current task.
        /// Create one if no task present.
        /// 
        /// Close the current task.
        /// </summary>
        /// <param name="errCode"></param>
        /// <returns></returns>
        public bool AddErrorRetFalse(string errCode)
        {
            if(_currAppTask==null)
                StartTask("Undefined");

            _currAppTask.AddError(errCode);
            return false;
        }


        //---------------------------------------------------------------------
        public object AddErrorRetNull(string errCode, string param)
        {
            AddErrorRetFalse(errCode, param,"");
            return null;
        }

        #endregion
    }
}
